'    Copyright 2008 Jan Molnar <jan.molnar@abds.de>
'
'    This file is part of JCQ.

'    JCQ is free software: you can redistribute it and/or modify
'    it under the terms of the GNU General Public License as published by
'    the Free Software Foundation, either version 2 of the License, or
'    (at your option) any later version.

'    JCQ is distributed in the hope that it will be useful,
'    but WITHOUT ANY WARRANTY; without even the implied warranty of
'    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'    GNU General Public License for more details.

'    You should have received a copy of the GNU General Public License
'    along with JCQ. If not, see <http://www.gnu.org/licenses/>.

Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Imports System.Windows.Threading

Public Class NotifyingCollectionBinding(Of T)
    Inherits DispatcherObject

    Private _source As INotifyCollectionChanged
    Private _target As ObservableCollection(Of T)

    Public Sub New(ByVal source As INotifyCollectionChanged, ByVal target As ObservableCollection(Of T))
        _source = source
        _target = target

        AddHandler _source.CollectionChanged, AddressOf OnSourceChanged
    End Sub

    Public Sub Close()
        RemoveHandler _source.CollectionChanged, AddressOf OnSourceChanged
    End Sub

    Protected Overridable Sub OnSourceChanged(ByVal sender As Object, ByVal e As NotifyCollectionChangedEventArgs)
        Try
            Select Case e.Action
                Case Specialized.NotifyCollectionChangedAction.Add
                    TargetInsert(e.NewStartingIndex, GetTargetItem(e.NewItems(0)))
                Case Specialized.NotifyCollectionChangedAction.Remove
                    TargetRemove(GetTargetItem(e.OldItems(0)))
                Case Specialized.NotifyCollectionChangedAction.Replace
                    TargetItem(e.NewStartingIndex) = GetTargetItem(e.NewItems(0))
                Case Specialized.NotifyCollectionChangedAction.Reset
                    TargetClear()
                Case Specialized.NotifyCollectionChangedAction.Move
                    TargetMove(e.OldStartingIndex, e.NewStartingIndex)
            End Select
        Catch ex As Exception
            Core.Kernel.Exceptions.PublishException(ex)
        End Try
    End Sub

    Protected Overridable Function GetTargetItem(ByVal item As Object) As T
        Return DirectCast(item, T)
    End Function

    Protected Sub TargetInsert(ByVal index As Integer, ByVal item As T)
        Dispatcher.BeginInvoke(DispatcherPriority.Normal, New Action(Of Integer, T)(AddressOf _target.Insert), index, item)
    End Sub

    Protected Sub TargetAdd(ByVal item As T)
        Dispatcher.BeginInvoke(DispatcherPriority.Normal, New Action(Of T)(AddressOf _target.Add), item)
    End Sub

    Protected Sub TargetMove(ByVal oldIndex As Integer, ByVal newIndex As Integer)
        Dispatcher.BeginInvoke(DispatcherPriority.Normal, New Action(Of Integer, Integer)(AddressOf _target.Move), oldIndex, newIndex)
    End Sub

    Protected Sub TargetRemove(ByVal item As T)
        Dispatcher.BeginInvoke(DispatcherPriority.Normal, New Action(Of T)(AddressOf _target.Remove), item)
    End Sub

    Protected Property TargetItem(ByVal index As Integer) As T
        Get
            Return _target(index)
        End Get
        Set(ByVal value As T)
            Dispatcher.Invoke(DispatcherPriority.Normal, New Action(Of Integer, T)(AddressOf TargetSetItem), index, value)
        End Set
    End Property

    Protected Sub TargetSetItem(ByVal index As Integer, ByVal item As T)
        _target(index) = item
    End Sub

    Protected Sub TargetClear()
        Dispatcher.Invoke(DispatcherPriority.Normal, New Action(AddressOf _target.Clear))
    End Sub
End Class